#ifndef Define_LcPostProcessing
#define Define_LcPostProcessing

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include "LcBasic.h"

using namespace std;
using namespace cv;

void getLabelMask( Mat & res, Mat & mask , Size size, int bound_setting = 0);

void sampleFromContour( Mat & res_mask, vector< vector<Point2f> > & points ,
					   vector< Mat > * p_contour_images = NULL);

void drawPoints( Mat & dsp, vector< Point2f > & points);

//=====================================

typedef Point2f ControlPoint;
typedef vector<Point2f > ControlPoints;

class LcPoly
{
public:
	int point_n; 

	LcPoly( ControlPoints & points);

	virtual Point2f getNormal( int i );
	virtual Point2f getTangent( int i);
		
	Point2f getPrevious(int i);
	Point2f getNext(int i);

	void calueCenter();

	ControlPoints controlpoints;

	Point2f center;

};


//================================

class ContourObserve
{
public:
	virtual float predict( Mat & frm, ControlPoints & contour ){return 0;}
};

class LcSnake: public ContourObserve
{
public:
	virtual float predict( Mat & frm, ControlPoints & contour );

	virtual float predict_point(  Mat & frm, LcPoly & contour ,int point_id, Point2f & force);

	virtual float combine_score( vector< float > & scores );

	void resampleChain( ControlPoints & points );
};

//=================================

class ContourPF
{
public:
	//Init

	ContourPF();

	void init(  vector< Point2f > & , int n );


	//Dynamic

	void motion( ); // right now just gaussian noise


	//Observation

	ContourObserve * my_observer;

	void updataWeight( Mat & mask );


	//other

	void draw(Mat & frm, Mat & dsp);

	void getPosterior( Mat & res, Size _size);

	void setParticleN( int n );

	void resample( );

	ControlPoints getMAP();

private:
	//Init


	//Dynamic

	float shape_noise;
	float motion_noise;
	float angle_noise;

	//Observation


	//other

	int dim_n;

	int particle_n;

	vector< float >  weights;

	vector< ControlPoints > particles;

	
};

//=====================================

#include "Classifier.h"

class MultiTracker
{
public:

	void work( Mat & mask_res ); // 8U

	void drawDebug(Mat & dsp);

	void getPosterior( Mat & res, Size _size);

	

	int obj_to_tracking;

	int num_tracker_working;

	float precision_lower_bound;

	float overlapping_upper_bound;

	MultiTracker()
	{
		obj_to_tracking = 3;

		my_trackers.resize( obj_to_tracking );

		res_tracker.resize( obj_to_tracking );

		score_tracker.resize( obj_to_tracking );

		if_tracker_working.resize( obj_to_tracking );

		for(int i = 0 ; i < obj_to_tracking; i++)
			if_tracker_working[ i ] = 0;
	
		precision_lower_bound = 0.8f;

		overlapping_upper_bound = 0.5f;
	}

	void samplingContour( Mat & mask_res );	

	void updataTracker( Mat & mask_res );

	void validatePartly();

	void removeOverlappingTracker( );

	void removeSeparate();

	void newTracker( Mat & mask_res );

	void replaceRes();

	void replaceTracker();

	void draw( Mat & dsp );

	void preprocessing( Mat & mask_res );
	
private:
	vector< ContourPF > my_trackers;

	vector< int > if_tracker_working;

	vector< Mat > res_tracker; //output by updataTracker

	vector< Mat > res_postprocessing; //output by samplingContour
	vector< ControlPoints > points_postprocessing; //output by samplingContour

	vector< LcValidator > score_tracker; 

	vector< vector< LcValidator > > tracker_on_part;

	static LcValidator predict( Mat & res, Mat & lab ,unsigned char th = 100);

};




#endif